'''
Created on Jul 17, 2012

@author: daoxuandung
'''
from google.appengine.ext import ndb
from kid import util
import logging
from entity.entity import Article, Board, Note
from datetime import datetime, timedelta, date
from operator import attrgetter
from app import board_async, cache_helper
from web import settings

@ndb.tasklet
def get_all(**q_options):
    qry = Article.query().order(-Article.created_time)
    (articles, cur, more) = yield qry.fetch_page_async(settings.BATCH_SIZE,**q_options)
    raise ndb.Return(articles, cur, more)


@ndb.tasklet
def get_all_by_user(user_key, **q_options):
    qry = Article.query(Article.author == user_key).order(-Article.created_time)
    articles = yield qry.fetch_async(**q_options)
    raise ndb.Return(articles)
    

@ndb.tasklet
def get_top_views(day=None, week=None, month=None, year=None, **q_options):
    """
    Get top views articles
    """        
    qry = Article.query(Article.day==day, 
                        Article.month==month, 
                        Article.year==year)
    # Order by views
    qry = qry.order(-Article.views, -Article.created_time)
    qry_date = datetime.date(day, month, year)
    (articles, cur, more) = yield qry.fetch_page_async(settings.BATCH_SIZE, **q_options)
    
    # If the current day has been fetched, fetch the previous day
    if len(articles) < settings.BATCH_SIZE:
        qry_date = date(year, month, day) - timedelta(days=1)
        qry = Article.query(Article.day==qry_date.day,
                            Article.month==qry_date.month,
                            Article.year==qry_date.year)
        qry = qry.order(-Article.views, -Article.created_time)
        (next_articles, cur, more) = yield qry.fetch_page_async(settings.BATCH_SIZE-len(articles),
                                                                **q_options)
        articles = articles + next_articles
        
        
    raise ndb.Return(articles, cur, more, qry_date)


@ndb.tasklet
def get_top_vote(day=None, week=None, month=None, year=None, start_cursor=None):
    """
    Get top vote up articles last 30 days
    """
    # Cache top vote for 3 seconds
    data = cache_helper.get_top_vote_articles(day, month, year, start_cursor=start_cursor)    
    if data is not None:
        logging.info('data get from cache')
        logging.info(data)
        (articles, cur, more) = data
    else:
        logging.info('data not cache')
        qry = Article.query(Article.day==day, 
                            Article.month==month, 
                            Article.year==year)
        # Order by vote
        qry = qry.order(-Article.vote_up, -Article.created_time)
        (articles, cur, more) = yield qry.fetch_page_async(settings.BATCH_SIZE, start_cursor=start_cursor)
        if cur:
            logging.info('cur' + cur.urlsafe())
        cache_helper.set_top_vote_articles(day, month, year, data=(articles, cur, more))
    
    if len(articles) < settings.BATCH_SIZE:
        logging.info("len articles: " + str(len(articles)))
        qry_date = date(year, month, day) - timedelta(days=1)
        # Get from cache
        day = qry_date.day
        month = qry_date.month
        year = qry_date.year
        next_data = cache_helper.get_top_vote_articles(day, month, year, start_cursor=cur)
        if next_data is not None:
            (next_articles, cur, more) = next_data
            
        # If data not in cache, query and put in cache
        else:
            qry = Article.query(Article.day==day,
                                Article.month==month,
                                Article.year==year)
            qry = qry.order(-Article.vote_up, -Article.created_time)
            (next_articles, cur, more) = yield qry.fetch_page_async(settings.BATCH_SIZE-len(articles),
                                                                    start_cursor=cur)
            cache_helper.set_top_vote_articles(day, month, year, data=(next_articles, cur, more))
            
        articles = articles + next_articles
        logging.info("len next articles: " + str(len(articles)))
        
    raise ndb.Return(articles, cur, more)


@ndb.tasklet
def get_by_board(board_key):
    """
    Get list of articles inside board list
    """
    notes = yield board_async.get_notes_by_board(board_key)
    article_keys = [x.article for x in notes]
    articles = yield ndb.get_multi_async(article_keys)
    articles = sorted(articles, key=attrgetter('created_time'), reverse=True)
    logging.info(articles)
    raise ndb.Return(articles)
